#include "EventManager.h"
#include <algorithm>

#define SAFE_DELETE(p){if (p){delete p;p = NULL;}}

EventManager::EventManager(void)
	{
		ptrCola = &colaEventosSecundaria;
	}

void EventManager::addListener( TipoEvento tipo, EventListener *listener,bool prioritario )
	{
		if (listeners[tipo] == NULL)
			listeners[tipo] = new std::list<EventListener*>();
		//if (tipo == RATON_MOVIDO)
			//exit(-1);
		if (prioritario)
			listeners[tipo]->push_front(listener);
		else
			listeners[tipo]->push_back(listener);
	}

void EventManager::enviarEvento( Event *e ,bool repetible)
	{
		if (listeners[e->tipo] != NULL){
			if (!repetible)
				if (ptrCola->size())
					if (ptrCola->front()->tipo == e->tipo){//comprobamos el anterior, deberiamos comprobar todos.
						SAFE_DELETE(e->datos);
						SAFE_DELETE(e);
						return;			
					}
			ptrCola->push(e);
		}
		else
		{
		SAFE_DELETE(e->datos);
		SAFE_DELETE(e);
		}
	}

EventManager::~EventManager(void)
	{
	map<TipoEvento,list<EventListener*>*>::iterator it;
	for (it = listeners.begin(); it != listeners.end(); ++it){//por cada lista en el map
		std::list<EventListener*> *listenersEvento = it->second;
		for (iterador = listenersEvento->begin(); iterador != listenersEvento->end(); ++iterador)//por cada elemento de la lista
			delete (*iterador);
		listenersEvento->clear();
		delete listenersEvento;
	}
}

void EventManager::addListenerPromiscuo( EventListener *listener )
	{
		promiscuo.push_back(listener);
	}

//tenemos 2 colas de eventos, una la que se esta ejecutando y la otra es la que va a recibir los eventos producidos
//durante los eventos. 
void EventManager::enviarEventos()
	{
	ptrCola = colaEventos.size () ? &colaEventosSecundaria : &colaEventos;
	ptr		= ptrCola == &colaEventosSecundaria ? &colaEventos : &colaEventosSecundaria;

	while(!ptr->empty()){
		Event *e = ptr->front();

		std::list<EventListener*> *listenersEvento = listeners[e->tipo]; 
		
		if (listenersEvento != NULL)
			for (iterador = listenersEvento->begin(); iterador != listenersEvento->end(); ++iterador) 
				if ((*iterador)->onEvent(e)) // si alguien retorna true es que lo ha consumido
					break;
							
		
		for (iterador = promiscuo.begin(); iterador != promiscuo.end(); ++iterador) 
			(*iterador)->onEvent(e);
			
		ptr->pop();
		
		SAFE_DELETE(e->datos);
		SAFE_DELETE(e);
	}
}

void EventManager::enviarEventoInstant( Event *e )
	{

	std::list<EventListener*> *listenersEvento = listeners[e->tipo]; 
	if (listenersEvento != NULL){
		for (iterador = listenersEvento->begin(); iterador != listenersEvento->end(); ++iterador) 
			if ((*iterador)->onEvent(e)){ // si alguien retorna true es que lo ha consumido
				break;
				}			
		}
	for (iterador = promiscuo.begin(); iterador != promiscuo.end(); ++iterador) 
		(*iterador)->onEvent(e);
	colaEventos.pop();
	SAFE_DELETE(e->datos);
	SAFE_DELETE(e);
	}

void EventManager::eliminarListener( EventListener *listener )
	{
		map<TipoEvento,list<EventListener*>*>::iterator it;
		std::list<EventListener*> *ptr = NULL;

		for (it = listeners.begin(); it != listeners.end(); ++it){
			ptr = it->second; 
			if (ptr)
				ptr->remove(listener);

		}
	}